package com.bnq.control.desktop.view;


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.bnq.control.R;
import com.oray.sunlogin.manager.util.DisplayUtils;


public class Mouse extends View {
	private Context context;

	private static final int MOUSE_STATUS_NORMAL = 1;
	private static final int MOUSE_STATUS_LEFT = 2;
	private static final int MOUST_STATUS_RIGHT = 3;
	private static final int MOUST_STATUS_MOVE = 4;
	private static final int MOUSE_STATUS_SCROLLER = 5;

	/**
	 * 外轮廓，边框1
	 */
	private Paint paint0;

	/**
	 * 外轮廓,边框2
	 */
	private Paint paint1;
	/**
	 * 普通状态，填充
	 */
	private Paint paint2;
	/**
	 * 点击状态，内部黄色区域
	 */
	private Paint paint3;
	/**
	 * 点击状态白色区域
	 */
	private Paint paint4;
	/**
	 * 用于判断点击状态
	 */
	private boolean leftClicked, rightClicked, centerClicked, bottomClicked,
			topClicked, smallMouseClicked;

	/**
	 * 顶部圆的Y值
	 */
	private int topY;
	/**
	 * 底部圆的Y值
	 */
	private int bottomY;

	/**
	 * 顶部和底部圆的半径
	 */
	private int topRad;

	/**
	 * 中心圆的半径
	 */
	private float centerRad;

	/**
	 * 左右键宽度半径
	 */
	private float left_with;

	/**
	 * 左键中心离中心圆的距离
	 */
	private int left_center_x;

	/**
	 * 对外抛出的监听
	 */
	private MouseListener mouseListener;

	/**
	 * 边框宽度，dp
	 */
	public static final int STROKE_WITH = 4;

	/**
	 * 中心圆的半径，dp
	 */
	public static final int RAD_CENTER = 30;

	/**
	 * 左右键与中心圆之间的间隙宽度，dp
	 */
	public static final int SPACE_WITH = 10;

	/**
	 * 鼠标中键的width
	 */
	private static final int CENTER_KEY_WIDTH = 28;

	/**
	 * 鼠标中键的height
	 */
	private static final int CENTER_KEY_HEIGHT = 44;

	/**
	 * 左键左弧度的半径,dp
	 */
	public static final int RAD1 = RAD_CENTER * 2 + SPACE_WITH + STROKE_WITH
			* 2;

	/**
	 * 左键右弧度的半径,dp
	 */
	public static final int RAD2 = RAD_CENTER + SPACE_WITH + STROKE_WITH;

	/**
	 * View的宽高，dp
	 */
	public static final int VIEW_SIZE = 156;

	/**
	 * 小鼠标的宽高，dp
	 */
	public static final int SMALL_MOUSE_SIZE = 35;

	/**
	 * 默认中心圆半径
	 */
	public static final int DEFAULT_CENTER_RAD = 30;

	/**
	 * 默认顶部圆半径
	 */
	public static final int DEFAULT_TOP_RAD = 13;

	/**
	 * 默认左键中心离中心圆的距离
	 */
	public static final int DEFAULT_LEFT_CENTER_X = 59;

	/**
	 * 远程菜单的宽度
	 */
	public static final int REMOTE_FUNCTION_MENU_WIDTH = 60;

	/**
	 * 左右键角度的1/2
	 */
	public static final int DEFAULT_ANGLE = 35;

	private static final int DELAY = 10 * 1000;

	private static final String TAG = "MOUSE";

	/**
	 * 是否是小鼠标
	 */
	private boolean isSmall = false;

	private boolean toSmallMouse = false;

	private Handler handler;

	private final int MSG_TO_SIDE = 1;

	private final int MSG_TO_CENTER = 2;

	private GestureDetector detector;

	private Runnable raRunnable;

	private boolean clickable = true;//kvm远程桌面时，有时无法点击

	private boolean smallMouseClickable;

	private Bitmap deleteMouse;
	private Bitmap smallMouse;
	private Bitmap smallMouseLight;

	private Bitmap remote_desktop_mouse_left;
	private Bitmap remote_desktop_mouse_move;
	private Bitmap remote_desktop_mouse_normal;
	private Bitmap remote_desktop_mouse_right;
	private Bitmap remote_desktop_mouse_scroller;


	private Bitmap mouse_center_key;
	private int deleteLeft;
	private float defaultWidth;
	private int currentMouseStatus;
	private boolean isDragStatus;
	private int minStep;


	private RectF smallRect;

	private final Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
		@Override
		public void onAnimationEnd(Animator animation) {
			smallMouseClickable = true;
		}
	};

	public Mouse(Context context) {
		super(context);
		init(context);
	}

	public Mouse(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public Mouse(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context);
	}

	/**
	 * 获取 中心圆的position
	 *
	 * @param point 指针坐标
	 * @return
	 */
	public Point getCenterPointPosition(Point point) {
		return new Point((int) (point.x + dp2px((VIEW_SIZE >> 1) - RAD_CENTER - STROKE_WITH, context)),
				(int) (point.y + dp2px((VIEW_SIZE >> 1) - RAD_CENTER - STROKE_WITH, context)));
	}

	/**
	 * 获取小圆的position
	 *
	 * @param point 指针坐标
	 * @return
	 */
	public Point getTopCirclePointPosition(Point point) {
		return new Point((int) (point.x + dp2px((VIEW_SIZE >> 1) - DEFAULT_TOP_RAD, context)), point.y);
	}

	/**
	 * 获取中心圆的宽高
	 *
	 * @return
	 */
	public Point getCenterPoint() {
		return new Point((int) dp2px(RAD_CENTER + STROKE_WITH, context) * 2,
				(int) dp2px(RAD_CENTER + STROKE_WITH, context) * 2);
	}

	/**
	 * 获取小圆的宽高
	 *
	 * @return
	 */
	public Point getTopCirclePoint() {
		return new Point(DisplayUtils.dp2px(DEFAULT_TOP_RAD * 2, getContext()),
				DisplayUtils.dp2px(DEFAULT_TOP_RAD * 2, getContext()));
	}

	public void setMouseListener(MouseListener mouseListener) {
		this.mouseListener = mouseListener;
	}

	public void setMouseClickable(boolean clickable) {
		this.clickable = clickable;
	}

	public void mouseSideAnimation() {
		if (getTranslationY() + DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2
				- Mouse.SMALL_MOUSE_SIZE / 2, getContext()) < 0) {
			setTranslationY(-DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2 - Mouse.SMALL_MOUSE_SIZE / 2, getContext()));
		} else if (getTranslationY()
				+ DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2
				+ Mouse.SMALL_MOUSE_SIZE / 2, getContext()) > DisplayUtils
				.getScreenHeight(getContext())) {
			setTranslationY(DisplayUtils.getScreenHeight(getContext())
					- DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2
					+ Mouse.SMALL_MOUSE_SIZE / 2, getContext()));
		}

		if (getTranslationX()
				+ DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, getContext()) < DisplayUtils.getScreenWidth(getContext()) >> 1) {
			ObjectAnimator oa = ObjectAnimator.ofFloat(this, "translationX",
					DisplayUtils.dp2px(-Mouse.VIEW_SIZE / 2
							+ Mouse.SMALL_MOUSE_SIZE / 2, getContext()));
			oa.setDuration(500);
			oa.addListener(listener);
			oa.start();
		} else {
			// 吸边时不与右侧菜单栏重叠
			ObjectAnimator oa = ObjectAnimator.ofFloat(
					this, "translationX",
					DisplayUtils.getScreenWidth(getContext()) - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2
							+ Mouse.SMALL_MOUSE_SIZE / 2 , getContext()));
			oa.setDuration(500);
			oa.addListener(listener);
			oa.start();
		}
	}

	private void onSmallMouseMoveAnimation(float dx, float dy) {
		setTranslationX(getTranslationX() + dx);
		if ((dy < 0 && getTranslationY() + DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2 - Mouse.SMALL_MOUSE_SIZE / 2, getContext()) > 0)
				|| (dy > 0 && (getTranslationY() + dy) < DisplayUtils.getScreenHeight(getContext())
				- DisplayUtils.dp2px(Mouse.SMALL_MOUSE_SIZE, getContext()) * 2 - viewHeight)) {
			setTranslationY(getTranslationY() + dy);
		}
	}

	private void toCenterAnimation() {
		if (isSmall) {
			if (getTranslationX() < DisplayUtils.getScreenWidth(getContext()) >> 1) {
				ObjectAnimator.ofFloat(this, "translationX", 0)
						.setDuration(400).start();
			} else {
				ObjectAnimator.ofFloat(this, "translationX", DisplayUtils.getScreenWidth(getContext()) -
								DisplayUtils.dp2px(Mouse.VIEW_SIZE, getContext()))
						.setDuration(400).start();
			}

			if (getTranslationY() < 0) {
				ObjectAnimator.ofFloat(this, "translationY", 0)
						.setDuration(400).start();
			} else if (getTranslationY() > DisplayUtils.getScreenHeight(getContext()) -
					DisplayUtils.dp2px(Mouse.VIEW_SIZE, getContext())) {
				ObjectAnimator.ofFloat(this, "translationY", DisplayUtils.getScreenHeight(getContext()) -
								DisplayUtils.dp2px(Mouse.VIEW_SIZE, getContext()))
						.setDuration(400).start();
			}
		}
	}


	@SuppressLint("HandlerLeak")
	private void init(Context context) {
		this.context = context;
		currentMouseStatus = MOUSE_STATUS_NORMAL;
		minStep = 5;
		detector = new GestureDetector(getContext(), new GestureListener());
		detector.setDoubleTapTimeout(150);
		detector.setOnDoubleTapListener(new DoubleTapListener());
		handler = new Handler(Looper.getMainLooper()) {
			@Override
			public void handleMessage(@Nullable Message msg) {
				switch (msg.what) {
					case MSG_TO_SIDE:
						if (mouseListener != null) {
							// 从大鼠标变成小鼠标时，吸边效果
							mouseSideAnimation();
							mouseListener.toSide();
							clearClick();
						}
						break;
					case MSG_TO_CENTER:
						if (mouseListener != null) {
							// 从小鼠标变成大鼠标时，大鼠标移动一段距离
							mouseListener.toCenter();
							clearClick();
						}
						toCenterAnimation();
						break;
				}
				super.handleMessage(msg);
			}
		};

		raRunnable = this::toSmallMouse;

		topY = DEFAULT_TOP_RAD + STROKE_WITH;
		bottomY = VIEW_SIZE - DEFAULT_TOP_RAD - STROKE_WITH;
		topRad = DEFAULT_TOP_RAD;
		centerRad = DEFAULT_CENTER_RAD;
		left_with = DEFAULT_TOP_RAD;
		left_center_x = DEFAULT_LEFT_CENTER_X;

		paint0 = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint0.setStyle(Paint.Style.STROKE);
		paint0.setColor(Color.parseColor("#999999"));
		paint0.setStrokeWidth(dp2px(STROKE_WITH >> 1, context));

		paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint1.setStyle(Paint.Style.STROKE);
		paint1.setColor(Color.parseColor("#59000000"));
		paint1.setStrokeWidth(dp2px(STROKE_WITH >> 1, context));

		paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint2.setStyle(Paint.Style.FILL);
		paint2.setColor(Color.parseColor("#cce5e5e5"));

		paint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint3.setStyle(Paint.Style.FILL);
		paint3.setColor(Color.parseColor("#faba5a"));

		paint4 = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint4.setColor(Color.parseColor("#ffffff"));
		paint4.setStyle(Paint.Style.FILL);

		initResources();

	}


	private void initResources() {
		remote_desktop_mouse_normal = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.remote_desktop_mouse_normal);
		remote_desktop_mouse_left = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.remote_desktop_mouse_left);
		remote_desktop_mouse_right = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.remote_desktop_mouse_right);
		remote_desktop_mouse_move = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.remote_desktop_mouse_move);
		remote_desktop_mouse_scroller = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.remote_desktop_mouse_scroller);
		deleteMouse = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.mouse_delte);
		smallMouseLight = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.small_mouse_clicked);
		mouse_center_key = BitmapFactory.decodeResource(getResources(),
				R.drawable.remote_desktop_mouse_center_key);

		deleteLeft = DisplayUtils.dp2px(VIEW_SIZE - 2, getContext()) - deleteMouse.getWidth();
		smallMouse = BitmapFactory.decodeResource(getContext().getResources(),
				R.drawable.small_mouse);
		smallRect = new RectF(
				dp2px((VIEW_SIZE - SMALL_MOUSE_SIZE) >> 1, context), dp2px(
				(VIEW_SIZE - SMALL_MOUSE_SIZE) >> 1, context), dp2px(
				(VIEW_SIZE + SMALL_MOUSE_SIZE) >> 1, context), dp2px(
				(VIEW_SIZE + SMALL_MOUSE_SIZE) >> 1, context));
		defaultWidth = dp2px(VIEW_SIZE >> 1, context);

	}

	class DoubleTapListener implements GestureDetector.OnDoubleTapListener {

		@Override
		public boolean onSingleTapConfirmed(MotionEvent e) {

			return false;
		}

		@Override
		public boolean onDoubleTap(MotionEvent e) {
			float x = e.getX();
			float y = e.getY();
			float x1 = dp2px(VIEW_SIZE >> 1, getContext());
			float y1 = dp2px(VIEW_SIZE >> 1, getContext());
			float rad1 = dp2px(RAD_CENTER + STROKE_WITH, getContext());
			if ((x - x1) * (x - x1) + (y - y1) * (y - y1) <= rad1 * rad1 && !isSmall) {
				if (mouseListener != null) mouseListener.OnCenterDoubleCLick();
				smallMouseClickable = false;
			}
			return false;
		}

		@Override
		public boolean onDoubleTapEvent(MotionEvent e) {
			return false;
		}

	}

	class GestureListener implements GestureDetector.OnGestureListener {
		@Override
		public boolean onDown(MotionEvent e) {
			return false;
		}

		@Override
		public void onShowPress(MotionEvent e) {
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			float x = e.getX();
			float y = e.getY();

			if (mouseListener != null) {
				if (isSmall) {
					float x1 = defaultWidth;
					float y1 = defaultWidth;
					if (x > x1 - dp2px(SMALL_MOUSE_SIZE >> 1, context)
							&& x < x1 + dp2px(SMALL_MOUSE_SIZE >> 1, context)
							&& y > y1 - dp2px(SMALL_MOUSE_SIZE >> 1, context)
							&& y < y1 + dp2px(SMALL_MOUSE_SIZE >> 1, context)) {
						mouseListener.OnSmallMouseClick();
					}

				} else {
					if (x < DisplayUtils.dp2px(VIEW_SIZE, context) && x > DisplayUtils.dp2px(VIEW_SIZE - 20, context)
							&& y > 0 && y < DisplayUtils.dp2px(20, context)) {
						toSmallMouse();
						smallMouseClickable = false;
						mouseListener.OnDeleteClick();
					}
				}
			}
			return false;
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			return false;
		}
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		super.onLayout(changed, left, top, right, bottom);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = measureDimension((int) dp2px(VIEW_SIZE, context), widthMeasureSpec);
		int height = measureDimension((int) dp2px(VIEW_SIZE, context), heightMeasureSpec);
		setMeasuredDimension(width, height);
	}

	public int measureDimension(int defaultSize, int measureSpec) {
		int result;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);

		if (specMode == MeasureSpec.EXACTLY) {
			result = specSize;
		} else {
			result = defaultSize; // UNSPECIFIED
			if (specMode == MeasureSpec.AT_MOST) {
				result = Math.min(result, specSize);
			}
		}
		return result;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.save();
		if (isSmall) {
			if (smallMouseClicked) {
				drawSmallMouseClicked(canvas);
			} else {
				drawSmallMouse(canvas);
			}
		} else {
			if (!topClicked) {
				// 画左上角的鼠标
				drawCursor(canvas);
				//画右上角删除键
				drawDelete(canvas);
			}
			// 画左键，三种状态：1.普通状态 2.点击高亮状态 3.隐藏状态
			if (!topClicked) {
				drawLeft(canvas, paint0, left_with, left_center_x, -1);
				drawLeft(canvas, paint1, left_with, left_center_x, -3);
				if (!leftClicked) {
					drawLeft(canvas, paint2, left_with, left_center_x, 0);
				} else {
					drawLeft(canvas, paint4, left_with, left_center_x, 0);
					drawLeftClicked(canvas, paint3, 2);
				}
			}

			// 画右键，三种状态：1.普通状态 2.点击高亮状态 3.隐藏状态
			if (!topClicked) {
				drawRight(canvas, paint0, left_with, left_center_x, -1);
				drawRight(canvas, paint1, left_with, left_center_x, -3);
				if (!rightClicked) {
					drawRight(canvas, paint2, left_with, left_center_x, 0);
				} else {
					drawRight(canvas, paint4, left_with, left_center_x, 0);
					drawRightClicked(canvas, paint3, 2);
				}
			}

			// 画中心圆，三种状态：1.普通状态 2.点击高亮状态 3.隐藏状态
			if (!topClicked) {
				drawCenter(canvas, paint0, centerRad, 1);
				drawCenter(canvas, paint1, centerRad, 3);
				if (!centerClicked) {
					drawCenter(canvas, paint2, centerRad, 0);
				} else {
					drawCenter(canvas, paint4, centerRad, 0);
					drawCenterClicked(canvas, paint3, 2);
				}
			}

			// 画底部圆，位置根据Y变化,三种状态：1.普通状态 2.点击高亮状态 3.隐藏状态
			if (!topClicked) {
				drawBottomCircle(canvas, paint0, bottomY, topRad, 1);
				drawBottomCircle(canvas, paint1, bottomY, topRad, 3);

				if (bottomClicked) {
					drawBottomCircle(canvas, paint3, bottomY, topRad, 0);
				} else {
					drawBottomCircle(canvas, paint2, bottomY, topRad, 0);
				}
				drawBottom(canvas, topRad);
			}

			// 画顶部圆,单击效果由CircleScroll显示
			if (!topClicked) {
				drawTop(canvas, paint0, topY, topRad, 1);
				drawTop(canvas, paint1, topY, topRad, 3);
				drawTop(canvas, paint2, topY, topRad, 0);
			}

			// 10s 没有刷新变成小鼠标
			if (raRunnable != null) handler.removeCallbacks(raRunnable);
			if (!cancelTask) handler.postDelayed(raRunnable, DELAY);
		}
		canvas.restore();
	}

	private boolean cancelTask;

	public void cancelToSmallTask(boolean cancelTask) {            // 取消变成小鼠标的task
		this.cancelTask = cancelTask;
		if (!cancelTask && null != handler && null != raRunnable) {
			handler.postDelayed(raRunnable, DELAY);
		} else if (cancelTask && null != handler && null != raRunnable) {
			handler.removeCallbacks(raRunnable);
		}
	}

	private void drawCursor(Canvas canvas) {
		Bitmap cursorBitmap;
		switch (currentMouseStatus) {
			case MOUSE_STATUS_NORMAL:
				cursorBitmap = remote_desktop_mouse_normal;
				break;
			case MOUSE_STATUS_LEFT:
				cursorBitmap = remote_desktop_mouse_left;
				break;
			case MOUST_STATUS_RIGHT:
				cursorBitmap = remote_desktop_mouse_right;
				break;
			case MOUST_STATUS_MOVE:
				cursorBitmap = remote_desktop_mouse_move;
				break;
			case MOUSE_STATUS_SCROLLER:
				cursorBitmap = remote_desktop_mouse_scroller;
				break;
			default:
				cursorBitmap = remote_desktop_mouse_normal;
				break;
		}
		canvas.drawBitmap(cursorBitmap, 0, 0, null);
	}

	private void drawDelete(Canvas canvas) {
		canvas.drawBitmap(deleteMouse, deleteLeft, 0, null);
	}

	private void drawSmallMouse(Canvas canvas) {
		canvas.drawBitmap(smallMouse, null, smallRect, null);
	}

	private void drawSmallMouseClicked(Canvas canvas) {
		canvas.drawBitmap(smallMouseLight, null, smallRect, null);
	}

	public boolean isSmall() {
		return this.isSmall;
	}

	public boolean isSmallMouseClickable() {
		return this.smallMouseClickable;
	}

	/**
	 * 画鼠标左键
	 *
	 * @param canvas
	 * @param paint
	 * @param rad    上下两圆弧的半径（用于缩小）默认15
	 * @param x      圆弧中心到中心点的x距离（用于缩小）默认65
	 * @param dx     用于绘制点击时的高亮区域 dx表示空隙距离
	 */
	private void drawLeft(Canvas canvas, Paint paint, float rad, int x, int dx) {
		Path p = new Path();
		Double angleRadians = DEFAULT_ANGLE * Math.PI / 180;
		// 上圆弧的圆心位置
		float topx = Float.parseFloat(String.valueOf((VIEW_SIZE >> 1) - x
				* Math.cos(angleRadians)));
		float topy = Float.parseFloat(String.valueOf((VIEW_SIZE >> 1) - x
				* Math.sin(angleRadians)));
		// 绘制左键左圆弧
		RectF f1 = new RectF(dp2px((VIEW_SIZE >> 1) - (x + rad) + dx, context),
				dp2px((VIEW_SIZE >> 1) - (x + rad) + dx, context), dp2px((VIEW_SIZE >> 1) + (x + rad) - dx, context), dp2px((VIEW_SIZE >> 1)
				+ (x + rad) - dx, context));
		// 绘制左键上圆弧
		RectF f2 = new RectF(dp2px(topx - rad + dx, context), dp2px(topy - rad
				+ dx, context), dp2px(topx + rad - dx, context), dp2px(topy
				+ rad - dx, context));
		// 绘制左键右圆弧
		RectF f3 = new RectF(dp2px((VIEW_SIZE >> 1) - (x - rad) - dx, context),
				dp2px((VIEW_SIZE >> 1) - (x - rad) - dx, context), dp2px((VIEW_SIZE >> 1) + (x - rad) + dx, context), dp2px(VIEW_SIZE / 2
				+ (x - rad) + dx, context));
		// 绘制左键下圆弧
		RectF f4 = new RectF(dp2px(topx - rad + dx, context), dp2px(VIEW_SIZE
				- topy - rad + dx, context), dp2px(topx + rad - dx, context),
				dp2px(VIEW_SIZE - topy + rad - dx, context));
		p.arcTo(f1, 180 - DEFAULT_ANGLE, DEFAULT_ANGLE * 2);
		p.arcTo(f2, -(180 - DEFAULT_ANGLE), 180);
		p.arcTo(f3, -(180 - DEFAULT_ANGLE), -DEFAULT_ANGLE * 2);
		p.arcTo(f4, -DEFAULT_ANGLE, 180);
		p.close();
		canvas.drawPath(p, paint);
	}

	/**
	 * 画点击时左键的高亮区域
	 */
	private void drawLeftClicked(Canvas canvas, Paint paint, int dx) {
		drawLeft(canvas, paint, DEFAULT_TOP_RAD, DEFAULT_LEFT_CENTER_X, dx);
	}

	/**
	 * 画鼠标右键
	 *
	 * @param canvas
	 * @param paint
	 * @param rad    上下两圆弧的半径（用于缩小）默认15
	 * @param x      圆弧中心到中心点的x距离（用于缩小）默认65
	 * @param dx     用于绘制点击时的高亮区域 dx表示空隙距离
	 */
	private void drawRight(Canvas canvas, Paint paint, float rad, int x, int dx) {
		Path p = new Path();
		Double angleRadians = DEFAULT_ANGLE * Math.PI / 180;
		// 左键上圆弧的圆心位置
		float topx = Float.parseFloat(String.valueOf(VIEW_SIZE / 2 - x
				* Math.cos(angleRadians)));
		float topy = Float.parseFloat(String.valueOf(VIEW_SIZE / 2 - x
				* Math.sin(angleRadians)));
		// 绘制右键右圆弧
		RectF f1 = new RectF(dp2px(VIEW_SIZE / 2 - (x + rad) + dx, context),
				dp2px(VIEW_SIZE / 2 - (x + rad) + dx, context), dp2px(VIEW_SIZE
				/ 2 + (x + rad) - dx, context), dp2px(VIEW_SIZE / 2
				+ (x + rad) - dx, context));
		// 绘制右键上圆弧
		RectF f2 = new RectF(dp2px(VIEW_SIZE - topx - rad + dx, context),
				dp2px(topy - rad + dx, context), dp2px(VIEW_SIZE - topx + rad
				- dx, context), dp2px(topy + rad - dx, context));
		// 绘制右键左圆弧
		RectF f3 = new RectF(dp2px(VIEW_SIZE / 2 - x + rad - dx, context),
				dp2px(VIEW_SIZE / 2 - x + rad - dx, context), dp2px(VIEW_SIZE
				/ 2 + x - rad + dx, context), dp2px(VIEW_SIZE / 2 + x
				- rad + dx, context));
		// 绘制右键下圆弧
		RectF f4 = new RectF(dp2px(VIEW_SIZE - topx - rad + dx, context),
				dp2px(VIEW_SIZE - topy - rad + dx, context), dp2px(VIEW_SIZE
				- topx + rad - dx, context), dp2px(VIEW_SIZE - topy
				+ rad - dx, context));
		p.arcTo(f1, DEFAULT_ANGLE, -DEFAULT_ANGLE * 2);
		p.arcTo(f2, -DEFAULT_ANGLE, -180);
		p.arcTo(f3, -DEFAULT_ANGLE, DEFAULT_ANGLE * 2);
		p.arcTo(f4, 180 + DEFAULT_ANGLE, -180);
		p.close();
		canvas.drawPath(p, paint);
	}

	/**
	 * 画点击时右键的高亮区域
	 *
	 * @param paint
	 */
	private void drawRightClicked(Canvas canvas, Paint paint, int dx) {
		drawRight(canvas, paint, DEFAULT_TOP_RAD, DEFAULT_LEFT_CENTER_X, dx);
	}

	/**
	 * 画鼠标中心圆
	 *
	 * @param canvas
	 * @param paint
	 * @param rad    默认32
	 * @param dx     用于绘制边框
	 */
	private void drawCenter(Canvas canvas, Paint paint, float rad, int dx) {
		canvas.drawCircle(defaultWidth, defaultWidth, dp2px(rad + dx, context), paint);
	}

	/**
	 * 画点击时鼠标中心圆的高亮区域
	 *
	 * @param dx 表示点击时的高亮区域离边界的距离
	 */
	private void drawCenterClicked(Canvas canvas, Paint paint, int dx) {
		canvas.drawCircle(defaultWidth, defaultWidth, dp2px(RAD_CENTER - dx, context), paint);
	}

	private void drawBottom(Canvas canvas, int rad) {
		canvas.drawBitmap(mouse_center_key, dp2px(VIEW_SIZE / 2 - 7, context), dp2px(
				VIEW_SIZE - rad - 15, context), null);
	}

	private void drawBottomCircle(Canvas canvas, Paint paint, int y, int rad, int dx) {
		canvas.drawCircle(defaultWidth, dp2px(y, context), dp2px(rad + dx, context), paint);
	}

	/**
	 * 画鼠标顶部圆，根据Y值变化
	 *
	 * @param canvas
	 * @param paint
	 * @param y
	 * @param rad    默认15
	 * @param
	 */
	private void drawTop(Canvas canvas, Paint paint, int y, int rad, int dx) {
		canvas.drawCircle(defaultWidth, dp2px(y, context), dp2px(rad + dx, context), paint);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (clickable) {
			if (!isSmall && !toSmallMouse) {
				if (raRunnable != null) handler.removeCallbacks(raRunnable);
				// 十秒内没有刷新过，则变成小鼠标
				if (event.getAction() == MotionEvent.ACTION_UP) {
					if (!cancelTask) handler.postDelayed(raRunnable, DELAY);
				}
				// 点击事件
				clickEvent(event);
				// 出现滚轮事件
				appearRoller(event);
				// 双击中心圆
				doubleClickCenter(event);
				// 移动鼠标
				moveMouse(event);
				//删除键
				delteEvent(event);
			} else {
				// 小鼠标的事件处理
				return smallMouseEvent(event);
			}
		} else {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				mouseListener.clickUnable();
			}
		}
		return true;

	}


	private void delteEvent(MotionEvent event) {
		detector.onTouchEvent(event);
	}

	/**
	 * 小鼠标事件
	 */
	private float prex, prey;

	private boolean smallMouseEvent(MotionEvent event) {
		detector.onTouchEvent(event);
		float x = event.getX();
		float y = event.getY();
		float x1 = defaultWidth;
		float y1 = defaultWidth;
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				if (x > x1 - dp2px(SMALL_MOUSE_SIZE / 2, context)
						&& x < x1 + dp2px(SMALL_MOUSE_SIZE / 2, context)
						&& y > y1 - dp2px(SMALL_MOUSE_SIZE / 2, context)
						&& y < y1 + dp2px(SMALL_MOUSE_SIZE / 2, context)) {
					prex = event.getRawX();
					prey = event.getRawY();
					smallMouseClicked = true;
					invalidate();
				} else {
					return false;
				}
				break;

			case MotionEvent.ACTION_MOVE:
				if (smallMouseClicked) {
					float dx = event.getRawX() - prex;
					float dy = event.getRawY() - prey;
					onSmallMouseMoveAnimation(dx, dy);
					if (this.mouseListener != null) {
						this.mouseListener.OnSmallMouseMove(dx, dy);
					}
					prex = event.getRawX();
					prey = event.getRawY();
				}
				break;

			case MotionEvent.ACTION_UP:
				smallMouseClicked = false;
				invalidate();
				if (this.mouseListener != null) {
					mouseListener.toSide();
					mouseSideAnimation();
				}
				break;
		}
		return true;
	}

	/**
	 * 鼠标移动事件
	 */
	private float xPre, yPre;// 绝对位置

	private void moveMouse(MotionEvent event) {
		if (centerClicked || leftClicked || rightClicked || bottomClicked) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				xPre = event.getRawX();
				yPre = event.getRawY();
			}
			if (MotionEvent.ACTION_MOVE == event.getAction()) {
				float dx = event.getRawX() - xPre;
				float dy = event.getRawY() - yPre;
				if (!isMouseMove) {
					isMouseMove = Math.abs(dx) >= minStep || Math.abs(dy) >= minStep;
					if (bottomClicked && isMouseMove) {
						currentMouseStatus = MOUSE_STATUS_SCROLLER;
					} else if (leftClicked && isMouseMove) {
						currentMouseStatus = MOUST_STATUS_MOVE;
					}
				}

				if (null != mouseListener) mouseListener.OnMouseMove(dx, dy);
				xPre = event.getRawX();
				yPre = event.getRawY();
			}
		}
	}

	private int viewHeight;

	public void setMouseMoveHeight(int height) {
		this.viewHeight = height;
		mouseMove(viewHeight);
	}

	private void mouseMove(int height) {
		int viewHeight = isSmall() ? DisplayUtils.dp2px(Mouse.SMALL_MOUSE_SIZE, getContext()) : 0;
		if (getTranslationY() > DisplayUtils.getScreenHeight(getContext()) - height) { // 需要平移
			int transY = (DisplayUtils.getScreenHeight(getContext()) - height) / 2 - viewHeight > 0 ?
					(DisplayUtils.getScreenHeight(getContext()) - height) / 2 - viewHeight : 0;
			setTranslationY(transY);
		}
	}

	/**
	 * 单击事件
	 *
	 * @param event
	 */
	private void clickEvent(MotionEvent event) {
		float x = event.getX();
		float y = event.getY();
		float x1 = defaultWidth;
		float y1 = defaultWidth;
		float rad1 = dp2px(RAD_CENTER + STROKE_WITH, context);
		float x2 = defaultWidth;
		float y2 = dp2px(DEFAULT_TOP_RAD + STROKE_WITH, context);
		float rad2 = dp2px(DEFAULT_TOP_RAD + STROKE_WITH, context);

		float x3 = defaultWidth;
		float y3 = dp2px(VIEW_SIZE - (DEFAULT_TOP_RAD + STROKE_WITH), context);
		float rad3 = dp2px(DEFAULT_TOP_RAD + STROKE_WITH, context);
		if (MotionEvent.ACTION_UP == event.getAction()) {
			clearClick();
		}
		if ((x - x1) * (x - x1) + (y - y1) * (y - y1) <= rad1 * rad1) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				centerClicked = true;
				currentMouseStatus = MOUSE_STATUS_NORMAL;
			}
			invalidate();
		} else if ((x - x2) * (x - x2) + (y - y2) * (y - y2) <= rad2 * rad2) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				topClicked = true;
			}
			invalidate();
		} else if ((x - x3) * (x - x3) + (y - y3) * (y - y3) <= rad3 * rad3) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				bottomClicked = true;
				if (mouseListener != null) {
					mouseListener.OnBottomDown();
				}
				if (!isDragStatus) {
					currentMouseStatus = MOUSE_STATUS_SCROLLER;
				} else {
					currentMouseStatus = MOUSE_STATUS_NORMAL;
				}
				isDragStatus = !isDragStatus;
			}
			invalidate();
		} else if (x < dp2px((VIEW_SIZE >> 1) - (DEFAULT_CENTER_RAD >> 1) - 15, context)) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				leftClicked = true;
				if (mouseListener != null) {
					mouseListener.OnLeftDown();
				}
				currentMouseStatus = MOUSE_STATUS_LEFT;
			}
			invalidate();
		} else if (x > dp2px((VIEW_SIZE >> 1) + (DEFAULT_CENTER_RAD >> 1) + 15,
				context) && y > dp2px(20, context)) {
			if (MotionEvent.ACTION_DOWN == event.getAction()) {
				rightClicked = true;
				if (mouseListener != null) {
					mouseListener.OnRightDown();
				}
				currentMouseStatus = MOUST_STATUS_RIGHT;
			}
			invalidate();
		}

	}


	/**
	 * 变成小鼠标
	 */
	public void toSmallMouse() {
		if (!isSmall) {
			toSmallMouse = true;
			ValueAnimator toSmallAnimate = ValueAnimator.ofInt(0, 100);
			toSmallAnimate.addUpdateListener(valueAnimator -> {
				int value = (int) valueAnimator.getAnimatedValue();
				if (centerRad >= 25) {
					centerRad = (float) (RAD_CENTER - 0.2 * value);
				}
				if (value >= 10 && value <= 25) {
					topRad = DEFAULT_TOP_RAD - (value - 10);
				}
				if (value <= 25) {
					topY = (DEFAULT_TOP_RAD + STROKE_WITH) + value * 2;
					bottomY = (VIEW_SIZE - DEFAULT_TOP_RAD - STROKE_WITH) - value * 2;
				}
				if (value > 25) {
					left_with = (float) (DEFAULT_TOP_RAD - 0.2 * (value - 25));
					left_center_x = DEFAULT_LEFT_CENTER_X - (value - 25);
				}
				if (value == 100) {
					centerRad = 25;
					topY = 71;
					bottomY = 97;
					topRad = -1;
					left_with = 2;
					left_center_x = -10;
					isSmall = true;
					toSmallMouse = false;
					smallMouseClicked = false;
					Message msg = Message.obtain(handler);
					msg.what = MSG_TO_SIDE;
					msg.sendToTarget();
				}
				invalidate();
			});
			toSmallAnimate.setDuration(100);
			toSmallAnimate.start();
		}
	}

	/**
	 * 变成大鼠标
	 */
	public void toBigMouse() {
		if (isSmall) {
			ValueAnimator toBigAnimate = ValueAnimator.ofFloat(0f, 1f);
			toBigAnimate.addUpdateListener(valueAnimator -> {
				float value = (float) valueAnimator.getAnimatedValue();
				if (value == 0) {
					isSmall = false;
				}
				centerRad = (RAD_CENTER - 25) * value + 25;
				topY = (int) (71 - (71 - (DEFAULT_TOP_RAD + STROKE_WITH)) * value);
				bottomY = (int) (((VIEW_SIZE - (DEFAULT_TOP_RAD + STROKE_WITH)) - 97) * value + 97);
				topRad = (int) ((DEFAULT_TOP_RAD + 1) * value - 1);
				left_with = (DEFAULT_TOP_RAD - 2) * value + 2;
				left_center_x = (int) ((DEFAULT_LEFT_CENTER_X + 10) * value - 10);
				if (value == 1) {
					centerRad = RAD_CENTER;
					topY = DEFAULT_TOP_RAD + STROKE_WITH;
					bottomY = VIEW_SIZE - (DEFAULT_TOP_RAD + STROKE_WITH);
					topRad = DEFAULT_TOP_RAD;
					left_with = DEFAULT_TOP_RAD;
					left_center_x = DEFAULT_LEFT_CENTER_X;
					Message msg = Message.obtain(handler);
					msg.what = MSG_TO_CENTER;
					msg.sendToTarget();
				}
				currentMouseStatus = MOUSE_STATUS_NORMAL;
				isDragStatus = false;
				invalidate();
			});
			toBigAnimate.setDuration(100);
			toBigAnimate.start();
		}
	}


	public boolean getIsSmall() {
		return isSmall;
	}

	/**
	 * 出现滚轮的事件处理
	 *
	 * @param event
	 */
	private void appearRoller(MotionEvent event) {
		if (topClicked) {
			if (mouseListener != null) {
				mouseListener.OnScrollMove(event);
			}
		}
	}

	/**
	 * 双击中心圆
	 *
	 * @param event
	 */
	private void doubleClickCenter(MotionEvent event) {
		detector.onTouchEvent(event);
	}

	private boolean isMouseMove;

	private void clearClick() {
		if (leftClicked) {
			leftClicked = false;
			if (mouseListener != null) {
				mouseListener.OnLeftUp();
			}
			currentMouseStatus = MOUSE_STATUS_NORMAL;
		}
		if (rightClicked) {
			rightClicked = false;
			if (mouseListener != null) {
				mouseListener.OnRightUp();
			}
			currentMouseStatus = MOUSE_STATUS_NORMAL;
		}
		if (centerClicked) {
			centerClicked = false;
			if (null != mouseListener)
				mouseListener.onCenterDown();
			currentMouseStatus = MOUSE_STATUS_NORMAL;
		}
		if (bottomClicked) {
			bottomClicked = false;
			if (mouseListener != null) {
				mouseListener.OnBottomUp();
			}
		}
		if (topClicked) {
			topClicked = false;
			if (mouseListener != null) {
				mouseListener.OnScrollUp();
			}
			currentMouseStatus = MOUSE_STATUS_NORMAL;
		}
		if (isMouseMove) {
			currentMouseStatus = MOUSE_STATUS_NORMAL;
			isDragStatus = false;
		}
		isMouseMove = false;
		invalidate();
	}

	public static float dp2px(float dipValue, Context context) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return dipValue * scale;
	}

	public static float px2dp(float pxValue, Context context) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return pxValue / scale;
	}

	public interface MouseListener {
		void OnLeftDown();

		void OnLeftUp();

		void OnRightUp();

		void OnRightDown();

		void OnBottomDown();

		void OnBottomUp();

		void OnCenterDoubleCLick();

		void onCenterDown();

		void OnMouseMove(float dx, float dy);

		void OnScrollMove(MotionEvent event);

		void OnScrollUp();

		void OnSmallMouseClick();

		void OnSmallMouseMove(float dx, float dy);

		void toSide();

		void toCenter();

		void clickUnable();

		void OnDeleteClick();
	}
}
